package mmi.gui.shape;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import mmi.gui.Application;

public class TextObject extends Shape {	
	protected TextObject(Point2D start, Point2D end) {
		super(start, end);
	}
	
	protected TextObject(int id, Point2D start, Point2D end) {
		super(id, start, end);
	}

	public TextObject(Point2D start, String text, Font font, Color colour)
	{
		super(start, start);
		this.start = start;
		this.text = text;
		this.font = font;
		this.fontSize = font.getSize();
		
		Application.Trace("C1 Start: " + start.getX() + "," + start.getY());
		
		createFont();
	
	}
	
	public TextObject(int id, Point2D start, String text, Font font, Color colour)
	{
		super(id, start, start);
		this.start = start;
		this.text = text;
		this.font = font;
		this.fontSize = font.getSize();
		
		Application.Trace("C2 Start: " + start.getX() + "," + start.getY());
		
		createFont();
	}
	
	@Override
	public boolean contains(Point2D position) {
		return isSide(position) != null;
	}

	@Override
	public void draw(Graphics2D g) {	
		g.setFont(font);
		FontMetrics metrics = g.getFontMetrics(font);
		
		textHeight = metrics.getHeight();
		
		if(text == null || text.equals(""))
			textWidth = 0;
		else
			textWidth = metrics.stringWidth(text);		
		
		if(text != null && !text.equals(""))
		{
			g.drawString(text, (int) start.getX(), (int) start.getY());
		}
		
		setShowBoundingBox(true);
		drawBoundingBox(g);
	}

	/**
	 * Draws a default bounding box. The default is to place 4 bounding boxes, in each corner one.
	 * For special bounding boxes per shape, override this function.
	 * @param g
	 */
	@Override
	public void drawBoundingBox(Graphics2D g)
	{
		if(showBoundingBox)
		{	
			g.setFont(font);
			FontMetrics metrics = g.getFontMetrics(font);
			
			textHeight = metrics.getHeight();
			
			if(text == null || text.equals(""))
				textWidth = 0;
			else
				textWidth = metrics.stringWidth(text);
			
			////////////////////////////////////////////
			////////////////////////////////////////////
			
			// top left
//			g.fillRect((int) (start.getX()), (int) (start.getY() - 0.5*textHeight), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
			
			// top right
//			g.fillRect((int) (start.getX() + textWidth - Shape.getBoundingBoxSize()), (int) (start.getY() - 0.5*textHeight), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
			
			// bottom right
//			g.fillRect((int) (start.getX() + textWidth - Shape.getBoundingBoxSize()), (int) (start.getY() - Shape.getBoundingBoxSize()), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
			
			// bottom left
//			g.fillRect((int) (start.getX()), (int) (start.getY() - Shape.getBoundingBoxSize()), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());

			////////////////////////////////////////////
			////////////////////////////////////////////

			Stroke defaultStroke = g.getStroke();
			g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0));

			// top
//			g.drawLine((int) start.getX(), (int) (start.getY() - 0.5*textHeight), (int) start.getX() + textWidth, (int) (start.getY() - 0.5*textHeight));
			
			// left
//			g.drawLine((int) start.getX(), (int) start.getY(), (int) start.getX(), (int) (start.getY() - 0.5*textHeight));
			
			// bottom
//			g.drawLine((int) start.getX(), (int) start.getY(), (int) start.getX() + textWidth, (int) start.getY());
			
			// right
//			g.drawLine((int) start.getX() + textWidth, (int) start.getY(), (int) start.getX() + textWidth, (int) (start.getY() - 0.5*textHeight));
	
			g.setStroke(defaultStroke);
		}
	}
	
	/**
	 * Test if a position is corresponding to one of the bounding boxes
	 * @param position to test for a bounding box
	 * @return Side if position corresponds to a bounding box, otherwise null
	 */
	@Override
	public Sides isSide(Point2D position)
	{
		
		int leftX = (int) (start.getX() <= end.getX() ? start.getX() : end.getX());
		int rightX = (int) (start.getX() <= end.getX() ? end.getX() : start.getX());
		
		int topY = (int) (start.getY() <= end.getY() ? start.getY() : end.getY());
		int bottomY = (int) (start.getY() <= end.getY() ? end.getY() : start.getY());
			
		@SuppressWarnings("unused")
		int halfWidth = (int) ((rightX - leftX) / 2 + leftX);
		@SuppressWarnings("unused")
		int halfHeight = (int) ((bottomY - topY) / 2 + topY);
		
		Rectangle2D topLeft = new Rectangle2D.Double(start.getX(), start.getY() - 0.5*textHeight, Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
		if(topLeft.contains(position))
		{
			Application.TraceDebug("TL side click detected");
			return Sides.TopLeft;
		}
		
		Rectangle2D topRight = new Rectangle2D.Double(start.getX() + textWidth - Shape.getBoundingBoxSize(), start.getY() - 0.5*textHeight, Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
		if(topRight.contains(position))
		{
			Application.TraceDebug("TR side click detected");
			return Sides.TopRight;
		}
			
		Rectangle2D belowLeft= new Rectangle2D.Double(start.getX(), start.getY() - Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
		if(belowLeft.contains(position))
		{
			Application.TraceDebug("BL side click detected");
			return Sides.BelowLeft;
		}
		
		Rectangle2D belowRight = new Rectangle2D.Double(start.getX() + textWidth - Shape.getBoundingBoxSize(), start.getY() - Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
		if(belowRight.contains(position))
		{
			Application.TraceDebug("BR side click detected");
			return Sides.BelowRight;
		}
		
//		Rectangle2D top = new Rectangle2D.Double(halfWidth - .5*Shape.getBoundingBoxSize(), topY, Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
//		if(top.contains(position))
//		{
//			Application.TraceDebug("T side click detected");
//			return Sides.Top;
//		}
//		
//		Rectangle2D right = new Rectangle2D.Double(rightX - Shape.getBoundingBoxSize(), halfHeight - 0.5*Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
//		if(right.contains(position))
//		{
//			Application.TraceDebug("R side click detected");
//			return Sides.Right;
//		}
//		
//		Rectangle2D below = new Rectangle2D.Double(halfWidth - .5*Shape.getBoundingBoxSize(), bottomY - Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
//		if(below.contains(position))
//		{
//			Application.TraceDebug("B side click detected");
//			return Sides.Below;
//		}
//		
//		Rectangle2D left = new Rectangle2D.Double(leftX, halfHeight - 0.5*Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize(), Shape.getBoundingBoxSize());
//		if(left.contains(position))
//		{
//			Application.TraceDebug("L side click detected");
//			return Sides.Left;
//		}
		
		return null;
	}
	
	@Override
	public void fill(Graphics2D g) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Shapes getShape() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getXMLRepresentation() {
		String s = "";
		
		s += "\t\t<Shape shapetype=\"TextObject\" id=\"" + id + "\">" + "\n";
		s += "\t\t\t<xstart>" + start.getX() + "</xstart>" + "\n";
		s += "\t\t\t<ystart>" + start.getY() + "</ystart>" + "\n";
		s += "\t\t\t<text>" + text + "</text>" + "\n";
		s += "\t\t\t<font>" + font.toString() + "</font>" + "\n";
		s += "\t\t\t<colour>" + lineColour + "</colour>" + "\n";
		s += "\t\t</Shape>";

		return s;
	}

	@Override
	public void makeTheShape() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String toString() {
		String s = "";
		
		s += "TextObject: [" + id + "]: " + start.getX() + " " + start.getY() + " " + text + " " + font.toString() + " " + lineColour;
		
		return s;
	}

	/**
	 * @return the text
	 */
	public String getText() {
		return text;
	}

	/**
	 * @param text the text to set
	 */
	public void setText(String text) {
		this.text = text;
	}

	/**
	 * @return the font
	 */
	public Font getFont() {
		return font;
	}

	/**
	 * @param font the font to set
	 */
	public void setFont(Font font) {
		this.font = font;
		createFont();
	}

	/**
	 * @return the fontSize
	 */
	public int getFontSize() {
		return fontSize;
	}

	/**
	 * @param fontSize the fontSize to set
	 */
	public void setFontSize(int fontSize) {
		this.fontSize = fontSize;
		createFont();
	}

	private void createFont()
	{
		font = new Font(typeFont, Font.PLAIN, fontSize);
	}
	
	private String text = "";
	private String typeFont = "Times New Roman";
	private Font font = null;
	private int fontSize = 16;
	
	private int textWidth = 0;
	private int textHeight = 0;
	
}
